package com.qyer.lxp.service.price.impl;

import com.qyer.lxp.common.framework.contants.CurrencyEnum;
import com.qyer.lxp.common.framework.core.BaseSpringService;
import com.qyer.lxp.common.framework.threadpool.AbstractAroundAdviceCallable;
import com.qyer.lxp.common.framework.threadpool.CommonThreadPool;
import com.qyer.lxp.dao.errorlog.TaskErrorLogMapper;
import com.qyer.lxp.dao.price.PriceMapper;
import com.qyer.lxp.dao.product.ProductInfoMapper;
import com.qyer.lxp.lxdao.price.IPriceDao;
import com.qyer.lxp.lxdao.product.IProductDao;
import com.qyer.lxp.model.errorlog.TaskErrorLog;
import com.qyer.lxp.model.price.normal.DailyPrice;
import com.qyer.lxp.model.price.normal.Price;
import com.qyer.lxp.model.price.parameter.AvailableDatesRequest;
import com.qyer.lxp.model.price.parameter.PeriodPriceQueryRequest;
import com.qyer.lxp.model.price.parameter.PriceQueryRequest;
import com.qyer.lxp.model.product.normal.ProductInfo;
import com.qyer.lxp.model.product.normal.ProductSpecfication;
import com.qyer.lxp.model.product.normal.SaleItemDetail;
import com.qyer.lxp.model.product.parameter.ProductInfoRequest;
import com.qyer.lxp.service.mail.ISendEmailService;
import com.qyer.lxp.service.price.IPriceService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 力行获取价格服务接口实现类
 * Created by jiangping on 16/5/18.
 */
@Service
public class PriceServiceImpl extends BaseSpringService implements IPriceService {

    @Resource
    private TaskErrorLogMapper taskErrorLogMapper;

    @Resource
    private IPriceDao priceDao;

    @Resource
    private PriceMapper priceMapper;

    @Resource
    private IProductDao productDao;

    @Resource
    private ISendEmailService sendEmailService;

    @Resource
    private ProductInfoMapper productInfoMapper;

    /**
     * 获取销售项目某一天的价格信息接口
     *
     * 据销售项目 code 和日期查询价格信息。如果是产品更新,
     * 建议使用下 面的 getPriceByPeriod 批量获取价格。
     *
     * @param priceQueryRequest 调取力行接口需要的参数
     * @return 返回查询条件内的价钱
     * @throws Exception
     */
    @Override
    public List<Price> getPriceByDay(PriceQueryRequest priceQueryRequest) {
        try {
            return priceDao.getPriceByDay(priceQueryRequest);
        } catch (Exception e) {
            logger.error("调用力行接口异常",e);
        }
        return null;
    }

    /**
     * 获取销售项目或者产品某一段时间的价格信息接口
     * <p>
     * 根据销售项目 code 或者产品 code 和日期查询价格信息。
     * 每次最多只返回 31 天的价格数据。
     *
     * @param periodPriceQueryRequest 调取力行接口需要的参数
     * @return 返回查询条件内的价钱
     * @throws Exception
     */
    @Override
    public List<DailyPrice> getPriceByPeriod(PeriodPriceQueryRequest periodPriceQueryRequest) {
        try {
            return priceDao.getPriceByPeriod(periodPriceQueryRequest);
        } catch (Exception e) {
            logger.error("调用力行接口异常",e);
        }
        return null;
    }

    /**
     * 获取销售项目的可售日期业务接口
     *
     * @param availableDatesRequest 销售code
     * @return 返回可售日期
     * @throws Exception
     */
    @Override
    public List<Date> getAvailableDates(AvailableDatesRequest availableDatesRequest) {
        try {
            return priceDao.getAvailableDates(availableDatesRequest);
        } catch (Exception e) {
            logger.error("调用力行接口异常",e);
        }
        return null;
    }

    /**
     * 批量插入产品价钱
     *
     * @param prices 产品价钱相关list
     * @return
     */
    @Override
    public void insertBatch(List<Price> prices) {
        priceMapper.insertBatch(prices);
    }

    /**
     * 根据量获取到的产品信息,将产品价钱批量插入到数据库
     * @param productCodeList 产品号列表
     */
    @Override
    public void insertBatchPrice(List<String> productCodeList) {
        if(null != productCodeList && productCodeList.size() > 0){
            for (String productCode:productCodeList) {
                try {
                    ProductInfoRequest productInfoRequest = new ProductInfoRequest();
                    productInfoRequest.setProductCode(productCode);
                    productInfoRequest.setCurrency("CNY");
                    productInfoRequest.setNeedSaleInfo("true");
                    ProductInfo productInfo = productDao.getProductInfo(productInfoRequest);
                    if(null != productInfo && null != productInfo.getSaleItemDetails()){
                        List<SaleItemDetail> saleItemDetailList = productInfo.getSaleItemDetails().getSaleItemDetailList();
                        for(SaleItemDetail saleItemDetail:saleItemDetailList){
                            AvailableDatesRequest availableDatesRequest = new AvailableDatesRequest();
                            availableDatesRequest.setSaleCode(saleItemDetail.getSaleCode());
                            List<Date> dateList = priceDao.getAvailableDates(availableDatesRequest);
                            if(null != dateList && dateList.size() > 0){
                                //list的长度
                                int length = dateList.size();
                                //每次允许查询的最大值
                                int pageSize = 30;
                                //根据每次查询的最大值计算次数，可以查几次
                                int pageCount = length%pageSize==0?(length/pageSize):(length/pageSize+1);
                                //按次数查询，list最大为200，包含200
                                for (int i=0;i<pageCount;i++){
                                    //查询的起始记录
                                    int start = 0;
                                    if(i == 0){
                                        start = i * pageSize;
                                    }else {
                                        start = i * pageSize + 1;
                                    }
                                    //查询的结束记录
                                    int end = (i + 1) * pageSize;
                                    //结束记录超出list的长度，使用list的长度
                                    if (end > length-1){
                                        end = length -1;
                                    }

                                    logger.info(length+","+pageCount+","+(i+1)+","+start+","+end);
                                    //获取查询的条数
                                    if((start > end) && (end%pageSize == 0)){
                                        break;
                                    }
                                    PeriodPriceQueryRequest periodPriceQueryRequest = new PeriodPriceQueryRequest();
                                    periodPriceQueryRequest.setSaleCode(saleItemDetail.getSaleCode());
                                    periodPriceQueryRequest.setTravelDate(dateList.get(start));
                                    periodPriceQueryRequest.setTravelDateEnd(dateList.get(end));
                                    periodPriceQueryRequest.setCurrency(CurrencyEnum.QYER_CURRENCY_CNY.getValue());
                                    List<DailyPrice> dailyPriceList = priceDao.getPriceByPeriod(periodPriceQueryRequest);
                                    if(null != dailyPriceList && dailyPriceList.size() > 0){
                                        for (DailyPrice dailyPrice:dailyPriceList){
                                            final List<Price> priceList = dailyPrice.getPriceList();
                                            if (null != priceList && priceList.size() > 0) {
                                                for (Price price : priceList) {
                                                    price.setSaleCode(saleItemDetail.getSaleCode());
                                                }
                                                CommonThreadPool.execute(new AbstractAroundAdviceCallable() {
                                                    @Override
                                                    public Object call() throws Exception {
                                                        priceMapper.insertBatch(priceList);
                                                        return null;
                                                    }
                                                });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    try {
                        TaskErrorLog countTaskErrorLog = new TaskErrorLog();
                        countTaskErrorLog.setParam(productCode);
                        int count = taskErrorLogMapper.countTaskErrorLog(countTaskErrorLog);
                        if(count <= 0){
                            TaskErrorLog taskErrorLog = new TaskErrorLog();
                            taskErrorLog.setParam(productCode);
                            taskErrorLog.setMethodName("updateBatchPrice");
                            taskErrorLogMapper.insertTaskErrorLog(taskErrorLog);
                        }
                    } catch (Exception e1) {
                        logger.error(e1);
                    }
                    logger.error(e);
                }
            }
        }
    }

    /**
     * 根据量获取到的产品信息,将产品价钱批量更新到数据库
     *
     * @param productCodeList 产品号列表
     */
    @Override
    public void updateBatchPrice(List<String> productCodeList) {
        if(null != productCodeList && productCodeList.size() > 0){
            Map<String,Map<String,List<Price>>> productMap = new HashMap<String, Map<String, List<Price>>>();
            Map<String,Map<String,String>> productSpecficationMap = new HashMap<String, Map<String,String>>();
            logger.info("更新日期价格开始。。。。。。。。。。。。。。。。。");
            for (String productCode:productCodeList) {
                try {
                    ProductInfoRequest productInfoRequest = new ProductInfoRequest();
                    productInfoRequest.setProductCode(productCode);
                    productInfoRequest.setCurrency("CNY");
                    productInfoRequest.setNeedSaleInfo("true");
                    ProductInfo productInfo = productDao.getProductInfo(productInfoRequest);
                    if(null != productInfo && null != productInfo.getSaleItemDetails()){

                        //组装发送邮件信息变量
                        Map<String,List<Price>> saleMap = new HashMap<String, List<Price>>();

                        //获取套餐列表
                        List<SaleItemDetail> saleItemDetailList = productInfo.getSaleItemDetails().getSaleItemDetailList();

                        //获取产品规格信息
                        List<ProductSpecfication> productSpecficationList = productInfoMapper.getProductSpecfication(productCode);

                        //组装规格ＩＤ与规格名称对应关系，后面生成邮件时使用
                        Map<String,String> specficationMap = new HashMap<String, String>();
                        if(null != productSpecficationList && productSpecficationList.size() > 0){
                            for(ProductSpecfication productSpecfication:productSpecficationList){
                                specficationMap.put(productSpecfication.getSpecificationId(),productSpecfication.getNameCn());
                            }
                        }
                        productSpecficationMap.put(productCode,specficationMap);

                        //根据套餐进行更新日期价格
                        for(SaleItemDetail saleItemDetail:saleItemDetailList){
                            AvailableDatesRequest availableDatesRequest = new AvailableDatesRequest();
                            availableDatesRequest.setSaleCode(saleItemDetail.getSaleCode());
                            List<Date> dateList = priceDao.getAvailableDates(availableDatesRequest);    //获取可售价格的日期列表
                            if(null != dateList && dateList.size() > 0){

                                //查找数据库是否有该套餐，如果没有进行插入操作
                                Price insertPriceParam = new Price();
                                insertPriceParam.setSaleCode(saleItemDetail.getSaleCode());
                                int insertPriceCount = priceMapper.countPrice(insertPriceParam);
                                if(insertPriceCount <= 0){
                                    List<Price> insertPrices = insertBatchSale(dateList,saleItemDetail.getSaleCode());  //插入套餐
                                    if(null != insertPrices && insertPrices.size() > 0){
                                        saleMap.put(saleItemDetail.getSaleCode(),insertPrices); //记录新插入的套餐，准备发送邮件
                                    }
                                }

                                //list的长度
                                int length = dateList.size();
                                PeriodPriceQueryRequest periodPriceQueryRequest = new PeriodPriceQueryRequest();
                                periodPriceQueryRequest.setSaleCode(saleItemDetail.getSaleCode());
                                periodPriceQueryRequest.setTravelDate(dateList.get(0));
                                periodPriceQueryRequest.setTravelDateEnd(dateList.get(length <= 7 ?length-1:6));
                                periodPriceQueryRequest.setCurrency(CurrencyEnum.QYER_CURRENCY_CNY.getValue());
                                List<DailyPrice> dailyPriceList = priceDao.getPriceByPeriod(periodPriceQueryRequest);
                                if(null != dailyPriceList && dailyPriceList.size() > 0){
                                    List<Price> comparePriceResult = new ArrayList<Price>();
                                    for (DailyPrice dailyPrice:dailyPriceList){
                                        List<Price> priceList = dailyPrice.getPriceList();
                                        if (null != priceList && priceList.size() > 0) {
                                            Price priceParam = new Price();
                                            priceParam.setSaleCode(saleItemDetail.getSaleCode());
                                            priceParam.setDate(dailyPrice.getDate());
                                            List<Price> priceLocalList = priceMapper.setlectPrice(priceParam);
                                            if(null != priceLocalList && priceLocalList.size() > 0){
                                                List<Price> priceResult = compareToPrice(priceList,priceLocalList);
                                                if(null != priceResult && priceResult.size() > 0){
                                                    logger.info("==========================打印力行结果:"+priceList);
                                                    logger.info("==========================打印本地数据库结果:"+priceLocalList);
                                                    logger.info("==========================打印发送邮件的比对结果:"+priceResult);
                                                    saleMap.put(saleItemDetail.getSaleCode(),priceResult);
                                                    comparePriceResult.addAll(priceResult);
                                                    break;
                                                }
                                            }else {
                                                logger.info("==========================打印新增加的更新内容，并准备发送邮件:"+priceList);
                                                saleMap.put(saleItemDetail.getSaleCode(),priceList);
                                                comparePriceResult.addAll(priceList);
                                            }
                                        }
                                    }
                                    /**
                                     * 更新日期价格有变动的套餐，
                                     * 并更新变动日期之后的所有日期价格
                                     * 或者插入新增加的日期价格
                                     */
                                    if(null != comparePriceResult && comparePriceResult.size() > 0){
                                        Price paramPrice = new Price();
                                        paramPrice.setSaleCode(saleItemDetail.getSaleCode());
                                        int countPrice = priceMapper.countPrice(paramPrice);
                                        if(countPrice > 0){
                                            for (Price comparePrice:comparePriceResult){
                                                comparePrice.setUpdateTime(new Date());
                                                priceMapper.updatePriceBySaleCode(comparePrice);
                                            }
                                        }else {
                                                priceMapper.insertBatch(comparePriceResult);
                                        }
                                    }
                                }
                            }
                        }
                        if(null != saleMap && saleMap.size() > 0){
                            productMap.put(productCode,saleMap);
                        }
                    }
                } catch (Exception e) {
                    try {
                        TaskErrorLog countTaskErrorLog = new TaskErrorLog();
                        countTaskErrorLog.setParam(productCode);
                        int count = taskErrorLogMapper.countTaskErrorLog(countTaskErrorLog);
                        if(count <= 0){
                            TaskErrorLog taskErrorLog = new TaskErrorLog();
                            taskErrorLog.setParam(productCode);
                            taskErrorLog.setMethodName("updateBatchPrice");
                            taskErrorLogMapper.insertTaskErrorLog(taskErrorLog);
                        }
                    } catch (Exception e1) {
                        logger.error(e1);
                    }
                    logger.error(e);
                }
            }

            try {
                List<SaleItemDetail> saleNames = productInfoMapper.getSaleNameMap();
                Map<String,String> saleNamesMap = new HashMap<String, String>();
                for(SaleItemDetail saleDetail:saleNames){
                    saleNamesMap.put(saleDetail.getSaleCode(),saleDetail.getSaleName());
                }
                if(null != productMap && productMap.size() > 0){
                    sendEmailService.priceSendMail(productMap,productSpecficationMap,saleNamesMap);
                }
            } catch (Exception e) {
                logger.error(e.toString());
            }
            logger.info("更新日期价格结束。。。。。。。。。。。。。。。");
        }
    }

    /**
     * 获取价格日历信息
     * @param saleCode
     * @return
     */
    public List<Price> getPrice(String saleCode){
        return priceMapper.getPrice(saleCode);
    }

    /**
     * 根据price中指定的属性查询日期价格表的数据
     *
     * @param price 与日期价格表对应的查询字段
     * @return 返回结果list
     */
    @Override
    public List<Price> selectPrice(Price price) {
        return priceMapper.setlectPrice(price);
    }

    /**
     * 按日期删除价格
     *
     * @param price 删除条件
     * @return 返回删除后的结果
     * @throws Exception
     */
    @Override
    public int deleteBatchByPrice(Price price) {
        try {
            return priceMapper.deleteBatchByPrice(price);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return 0;
    }

    /**
     * 按套餐code,规格id,变化日期进行价格更新
     *
     * @param price 需要更新的数据与更新条件
     * @return 返回最终结果
     */
    @Override
    public int updatePriceBySaleCode(Price price) {
        return priceMapper.updatePriceBySaleCode(price);
    }

    /**
     * 按条件统计数量
     *
     * @param price 统计数量查询条件
     * @return 返回统计结果
     */
    @Override
    public int countPrice(Price price) {
        return priceMapper.countPrice(price);
    }

    /**
     * 价格比较器
     * @param prices    力行日期价格集合
     * @param priceTarget  本地数据库日期价格集合
     * @return  返回不相等的结果
     */
    private List<Price> compareToPrice(List<Price> prices,List<Price> priceTarget){
        List<Price> priceList = new ArrayList<Price>();
        Map<String,Object> map = new HashMap<String, Object>();
        Iterator<Price> iterator = priceTarget.iterator();
        while (iterator.hasNext()){
            Price priceIter = iterator.next();
            map.put(priceIter.getSpecificationId(),priceIter);
        }
        for (Price price:prices){
            if(price.compareTo((Price) map.get(price.getSpecificationId())) != 0){
                Price priceId = (Price) map.get(price.getSpecificationId());
                price.setId(priceId.getId());
                priceList.add(price);
            }
        }
        return priceList;
    }

    /**
     * 插入套餐私用方法，用于更新价格日期时插入套餐
     * @param dateList  需要插入的套餐列表
     * @param saleCode  需要插入的套餐code
     * @return  返回新增套餐的某一天价格列表
     */
    private List<Price> insertBatchSale(List<Date> dateList, String saleCode){
        try {
            List<Price> prices = new ArrayList<Price>();
            boolean flag = true;
            //list的长度
            int length = dateList.size();
            //每次允许查询的最大值
            int pageSize = 30;
            //根据每次查询的最大值计算次数，可以查几次
            int pageCount = length%pageSize==0?(length/pageSize):(length/pageSize+1);
            //按次数查询，list最大为200，包含200
            for (int i=0;i<pageCount;i++){
                //查询的起始记录
                int start = 0;
                if(i == 0){
                    start = i * pageSize;
                }else {
                    start = i * pageSize + 1;
                }
                //查询的结束记录
                int end = (i + 1) * pageSize;
                //结束记录超出list的长度，使用list的长度
                if (end > length-1){
                    end = length -1;
                }

                logger.info(length+","+pageCount+","+(i+1)+","+start+","+end);
                //获取查询的条数
                if((start > end) && (end%pageSize == 0)){
                    break;
                }
                PeriodPriceQueryRequest periodPriceQueryRequest = new PeriodPriceQueryRequest();
                periodPriceQueryRequest.setSaleCode(saleCode);
                periodPriceQueryRequest.setTravelDate(dateList.get(start));
                periodPriceQueryRequest.setTravelDateEnd(dateList.get(end));
                periodPriceQueryRequest.setCurrency(CurrencyEnum.QYER_CURRENCY_CNY.getValue());
                List<DailyPrice> dailyPriceList = priceDao.getPriceByPeriod(periodPriceQueryRequest);
                if(null != dailyPriceList && dailyPriceList.size() > 0){
                    for (DailyPrice dailyPrice:dailyPriceList){
                        final List<Price> priceList = dailyPrice.getPriceList();
                        if (null != priceList && priceList.size() > 0) {
                            for (Price price : priceList) {
                                price.setSaleCode(saleCode);
                            }
                            if(flag){
                                prices.addAll(priceList);
                                flag = false;
                            }
                            CommonThreadPool.execute(new AbstractAroundAdviceCallable() {
                                @Override
                                public Object call() throws Exception {
                                    priceMapper.insertBatch(priceList);
                                    return null;
                                }
                            });
                        }
                    }
                }
            }
            return prices;
        } catch (Exception e) {
            logger.error(e.toString());
        }
        return null;
    }
}
